﻿#include "util.h"


// 每个车辆的停车信息
typedef struct CarInfo
{
	size_t no_;          // 车牌号
	size_t arrive_;      // 进入时间
	size_t leave_;       // 离开时间
	float expense_;      // 产生的费用
	size_t time_;        // 停留时间
}CarInfo;

void CarInfoInit(CarInfo* carInfo)
{
	carInfo->no_ = -1;
	carInfo->arrive_ = -1;
	carInfo->leave_ = -1;
	carInfo->expense_ = -1;
	carInfo->time_ = -1;
}
void CarInfoSetNo(CarInfo* carInfo, size_t no)
{
	carInfo->no_ = no;
}
void CarInfoPrint(CarInfo* carInfo)
{
	if (carInfo == NULL) 
	{
		printf("暂无信息!\n");
	}
	else
	{
		char tmp[128] = { 0 };
		GetTimeStr(carInfo->arrive_, tmp);
		printf("| %-30zd %-30s ", carInfo->no_, tmp);
		if ((int)carInfo->leave_ < 0)
		{
			printf("%-30s ", "暂未离开");
		}
		else
		{
			GetTimeStr(carInfo->leave_, tmp);
			printf("%-30s ", tmp);
		}
		((int)carInfo->expense_ < 0) ? printf("%-30s ", "暂未产生费用") : printf("%-30f ", carInfo->expense_);
		if ((int)carInfo->time_ < 0)
		{
			printf("%-30s\n", "无停留时间");
		}
		else
		{
			printf("%-zd时%-zd分%-zd秒\n", carInfo->time_ / 3600, (carInfo->time_ % 3600) / 60, carInfo->time_ % 60);
		}
	}
}
void CarInfoTablePrint()
{
	printf("| %-30s %-30s %-30s %-30s %-30s\n", "车牌号", "进入时间", "离开时间", "产生的费用", "停留时间");
}

#define DATA CarInfo
#define DATA_INIT CarInfoInit
#define DATA_PRINT CarInfoPrint
#define DATA_TABLE CarInfoTablePrint

const size_t INIT_NUM = 12;
const size_t CAPACITY_NUM = 2;
const size_t NOT_FOUND = -1;
typedef struct Sequence
{
	DATA* data_;
	size_t capacity_;
	size_t size_;
}Sequence;

// 顺序表初始化
void SequenceInit(Sequence* sequence);
// 顺序表插入
void SequenceInsert(Sequence* sequence, const DATA data, const size_t pos);
// 顺序表删除
void SequenceErase(Sequence* sequence, const size_t pos);
// 顺序表尾插
void SequencePushBack(Sequence* sequence, const DATA data);
// 顺序表检查容量
void SequenceCheckCapcity(Sequence* sequence);
// 顺序表打印
void SequencePrint(const Sequence* sequence);
// 顺序表查找 通过车牌号查找
size_t SequenceFind(const Sequence* sequence, const size_t no);
// 顺序表销毁 类似析构 我觉得这种题目用c++的模板和类写很方便 无奈是c 
// 要销毁是因为内部有malloc出来的数据 要free掉
void SequenceDestory(Sequence* sequence);
// 取顺序表的值
DATA SequenceAt(const Sequence* sequence, const size_t pos);
// 取顺序表的长度
size_t SequenceNum(const Sequence* sequence);
// 顺序表复制
void SequenceCopy(const Sequence* source, Sequence* dest);
// 顺序表反转
void SequenceReverse(Sequence* sequence);



void swap(DATA* a, DATA* b)
{
	DATA tmp = *a;
	*a = *b;
	*b = tmp;
}
void SequenceInit(Sequence* sequence)
{
	sequence->data_ = (DATA*)calloc(INIT_NUM ,sizeof(DATA));
	if (sequence->data_ == NULL)
	{
		printf("calloc fail in init!\n");
		exit(CALLOC_FAIL_CODE);
	}
	sequence->capacity_ = INIT_NUM;
	sequence->size_ = 0;
}
void SequenceCheckCapcity(Sequence* sequence)
{
	assert(sequence);
	if (sequence->data_ == NULL)
	{
		SequenceInit(sequence);
	}
	else
	{
		if (sequence->size_ >= sequence->capacity_)
		{
			DATA* tmp = (DATA*)realloc(sequence->data_,
				(sequence->capacity_ == 0 ? INIT_NUM : sequence->capacity_ * CAPACITY_NUM) * sizeof(DATA));
			if (tmp == NULL)
			{
				printf("realloc fail in check!\n");
				exit(REALLOC_FAIL_CODE);
			}
			else
			{
				sequence->data_ = tmp;
				sequence->capacity_ = sequence->capacity_ == 0 ? INIT_NUM : sequence->capacity_ * CAPACITY_NUM;
			}
		}
	}

}
void SequencePushBack(Sequence* sequence, const DATA data)
{
	assert(sequence);
	SequenceCheckCapcity(sequence);
	sequence->data_[sequence->size_++] = data;
}
void SequencePrint(const Sequence* sequence)
{
	if (sequence == NULL)
	{
		printf("null sequence point!\n");
	}
	else
	{
		DATA_TABLE();
		for (size_t i = 0; i < sequence->size_; ++i)
		{
			DATA_PRINT(&sequence->data_[i]);
		}
	}
}
void SequenceInsert(Sequence* sequence, const DATA data, const size_t pos)
{
	assert((int)pos >= 0 && pos < sequence->capacity_);
	assert(sequence != NULL);

	++sequence->size_;
	SequenceCheckCapcity(sequence);
	for (size_t end = sequence->size_; end > pos; --end)
	{
		swap(&sequence->data_[end], &sequence->data_[end - 1]);
	}
	sequence->data_[pos] = data;
}
size_t SequenceFind(const Sequence* sequence, const size_t no)
{
	assert(sequence != NULL);
	for (size_t i = 0; i < sequence->size_; ++i)
	{
		if (sequence->data_[i].no_ == no)
		{
			return i;
		}
	}
	return NOT_FOUND;
}
void SequenceDestory(Sequence* sequence)
{
	if (sequence == NULL || sequence->data_ == NULL)
	{
		return;
	}
	sequence->size_ = 0;
	sequence->capacity_ = 0;
	free(sequence->data_);
	sequence->data_ = NULL;
}
void SequenceErase(Sequence* sequence, const size_t pos)
{
	// 此处不允许改变顺序
	if (sequence == NULL || pos >= sequence->size_ || sequence->size_ == 0)
	{
		return;
	}
	for (size_t tmp = pos; tmp < sequence->size_ - 1; ++tmp)
	{
		swap(sequence->data_ + tmp, sequence->data_ + tmp + 1);
	}
	--sequence->size_;
}
DATA SequenceAt(const Sequence* sequence, const size_t pos)
{
	assert(sequence != NULL && pos < sequence->size_);
	return sequence->data_[pos];
}
size_t SequenceNum(const Sequence* sequence)
{
	return sequence == NULL ? 0 : sequence->size_;
}
void SequenceCopy(const Sequence* source, Sequence* dest)
{
	if (source == NULL || dest == NULL)
	{
		return;
	}

	SequenceDestory(dest);
	SequenceInit(dest);
	for (size_t pos = 0; pos < SequenceNum(source); ++pos)
	{
		SequencePushBack(dest, SequenceAt(source, pos));
	}
}
void SequenceReverse(Sequence* sequence)
{
	if (sequence == NULL || sequence->size_ == 0)
	{
		return;
	}
	size_t left = 0;
	size_t right = sequence->size_ - 1;
	while (left < right)
	{
		swap(sequence->data_ + left, sequence->data_ + right);
		++left;
		--right;
	}
}



// -----------------------------------------
typedef struct Stack
{
	Sequence seq_;
}Stack;

// Stack初始化
void StackInit(Stack* stack);
// Stack入元素
void StackPush(const DATA data, Stack* stack);
// Stack长度
size_t StackNum(const Stack* stack);
// Stack出元素
void StackPop(Stack* stack);
// Stack取栈顶
DATA StackTop(const Stack* stack);
// Stack打印
void StackPrint(const Stack* stack);
// Stack销毁 由于 Stack 底层是 Sequence 所以也需要销毁
void StackDestory(Stack* stack);
// Stack拷贝
void StackCopy(const Stack* source, Stack* dest);

void StackInit(Stack* stack)
{
	SequenceInit(&stack->seq_);
}
void StackPush(const DATA data, Stack* stack)
{
	assert(stack != NULL);
	SequencePushBack(&stack->seq_, data);
}
size_t StackNum(const Stack* stack)
{
	assert(stack != NULL);
	return SequenceNum(&stack->seq_);
}
void StackPop(Stack* stack)
{
	assert(stack != NULL);
	SequenceErase(&stack->seq_, SequenceNum(&stack->seq_) - 1);
}
DATA StackTop(const Stack* stack)
{
	assert(stack != NULL && StackNum(stack) != 0);
	return SequenceAt(&stack->seq_, SequenceNum(&stack->seq_) - 1);
}
void StackPrint(const Stack* stack)
{
	if (stack != NULL)
	{
		SequencePrint(&stack->seq_);
	}
}
void StackDestory(Stack* stack)
{
	if (stack != NULL)
	{
		SequenceDestory(&stack->seq_);
	}
}
void StackCopy(const Stack* source, Stack* dest)
{
	if (source != NULL && dest != NULL)
	{
		SequenceCopy(&source->seq_, &dest->seq_);
	}
}
void StackReverse(Stack* stack) 
{
	if (stack != NULL)
	{
		SequenceReverse(&stack->seq_);
	}
}
// ---------------------------------------------
typedef struct Queue
{
	Sequence seq_;
}Queue;

// Queue初始化
void QueueInit(Queue* queue);
// Queue销毁 由于queue底层是sequence 所以需要销毁
void QueueDestory(Queue* queue);
// Queue入元素
void QueuePush(const DATA data, Queue* queue);
// Queue出元素
void QueuePop(Queue* queue);
// Queue取队头元素
DATA QueueTop(const Queue* queue);
// Queue打印
void QueuePrint(const Queue* queue);
// Queue取长度
size_t QueueNum(const Queue* queue);
// Queue拷贝
void QueueCopy(const Queue* source, Queue* dest);

void QueueInit(Queue* queue)
{
	assert(queue != NULL);
	SequenceInit(&queue->seq_);
}
void QueueDestory(Queue* queue)
{
	if (queue != NULL)
	{
		SequenceDestory(&queue->seq_);
	}
}
void QueuePush(const DATA data, Queue* queue)
{
	assert(queue != NULL);
	SequencePushBack(&queue->seq_, data);
}
void QueuePop(Queue* queue)
{
	assert(queue != NULL);
	// SequenceErase 内部已经判断了条件 所以这里不需要再判断条件
	SequenceErase(&queue->seq_, 0);
}
DATA QueueTop(const Queue* queue)
{
	assert(QueueNum(queue) != 0);
	return SequenceAt(&queue->seq_, 0);
}
void QueuePrint(const Queue* queue)
{
	if (queue != NULL)
	{
		SequencePrint(&queue->seq_);
	}
}
size_t QueueNum(const Queue* queue)
{
	return queue == NULL ? 0 : SequenceNum(&queue->seq_);
}
void QueueCopy(const Queue* source, Queue* dest)
{
	if (source != NULL && dest != NULL)
	{
		SequenceCopy(&source->seq_, &dest->seq_);
	}
}